﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using Pdelvo.Minecraft.Network;
using Pdelvo.Minecraft.Protocol;
using Pdelvo.Minecraft.Protocol.Packets;
using System.Threading;

namespace Pdelvo.Minecraft.Examples
{
     public class ClientExample
    {
         public void Run()
         {
             //This is a short example of a chat bot. This chat bot can connect to a offline server and shout chat messages on it
             //we want to use the newest 12w18a protocol

             var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
             socket.Connect(new IPEndPoint(IPAddress.Loopback, 25566));
             //Because we want to work with streams we need to use the NetworkStream Wrapper class for our remoteSocket socket
             var networkStream = new NetworkStream(socket);
             //You cannot be sure that packets can be read fully. So we need the FullyReadStream.
             var fullyReadStream = new FullyReadStream(networkStream);
             //Because the minecraft network stuff uses big endian we need to translate it
             var bigEndianStream = new BigEndianStream(fullyReadStream);
             //Allright. This implementation can be used as a client or a server. because we wantto speak with a minecraft server we want to use the ServerRemoteInterface class. The constructor need a bigEndianStream and a protocol version. The current(12w18a) version is 32. But this does not mean that just pre rlease clients can connect. everypacket to identificate the version will work. You will have o change the version later if you know it.
             var remoteInterface = new ServerRemoteInterface(bigEndianStream, 32);
             //Build a handhsake packet
             HandshakeRequest request = new HandshakeRequest
             {
                 ProtocolVersion = 33,//12w21a
                 Username = "Chatbot",
                 Host = "127.0.0.1:25566"
             };
             remoteInterface.SendPacket(request);
             //Get the Encrpytion key request packet from the server which contains the public key
             var response = remoteInterface.ReadPacket() as EncryptionKeyRequest;
             var publicKey = Security.GenerateRSAPublicKey(response.PublicKey);

             //Generate a new random rc4 Key
             var aesKey = Security.GenerateAes128Key();

             //Encrypt the rc4 key with the public key
             byte[] encryptedKey = Security.RSAEncrypt(aesKey.getEncoded(), publicKey);
             //Send the encrypted rc4 key to the server
             var encryptionResponse = new EncryptionKeyResponse { SharedKey = encryptedKey };
             remoteInterface.SendPacket(encryptionResponse);
             //Read the empty Encryption key response packet
             remoteInterface.ReadPacket();

             //Change to encrypted mode
             remoteInterface.SwitchToAesMode(aesKey);
             //Send a login packet(im version 32 it does not need any parameters)
             remoteInterface.SendPacket(new LoginRequest());
             //server responses with a login response packet with some information
             var loginResponse = remoteInterface.ReadPacket() as LoginResponse;
             Console.WriteLine("I logged in. I got the entity id: " + loginResponse.EntityID);

             //Because the server whould kick the bot if it does not answer login packet we can get a event when a new packet is avialable
             remoteInterface.PacketReceived += (s, e) =>
             {
                 //If the packet is a keep alive packet send it back to the server
                 if (e.Packet is KeepAlive)
                 {
                     remoteInterface.SendPacket(e.Packet);
                 }
                 else if (e.Packet is ChatPacket)
                 {
                     //write chat messages to the console
                     Console.WriteLine((e.Packet as ChatPacket).Message);
                 }
             };
             //Start automatic packet reading
             remoteInterface.Run();

             while (true)
             {
                 //Send each line from the console to the server
                 string str = Console.ReadLine();
                 remoteInterface.SendPacket(new ChatPacket() { Message = str });
             }
         }
    }
}
